<template>
  <div>
    <div id="slide_unloack_wraper">
      <canvas width="310" height="155" id="slide_unloack_wraper1"></canvas>
      <div id="slide_unloack_inner">
        <canvas width="310" height="155" id="slide_unloack_inner1"></canvas>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "SlideToUnlock",
  data() {
    return {
      isSuccess: false, //是否滑动成功
    };
  },
  created() {},
  mounted() {
    // 将两张图片渲染在cavas上
    var canvas = document.getElementById("slide_unloack_wraper1");
    var block = document.getElementById("slide_unloack_inner1");
    var canvas_ctx = canvas.getContext("2d");
    var block_ctx = block.getContext("2d");
    var img = document.createElement("img");
    img.onload = function () {
      canvas_ctx.drawImage(img, 0, 0, 310, 155);
      block_ctx.drawImage(img, 0, 0, 310, 155);

      var blockWidth = w + r * 2; //滑块实际宽度
      var _y = y - r * 2 + 2; // 滑块实际的y坐标
      var ImageData = block_ctx.getImageData(x, _y, blockWidth, blockWidth); //拿到滑块的像素数据
      block.width = blockWidth; //将滑块dom元素的宽度设置成滑块的掉
      block_ctx.putImageData(ImageData, 0, _y);
    };
    img.crossOrigin = "Anonymous"; //防止图片报跨域的错
    img.src =
      "http://kexiepingtaieposter.hoohui.cn//registFile/fa5df7c9-445d-4b58-97c4-ad8b86a92241/Z0134_2020033134932.jpeg?time=" +
      new Date(); //加事件戳 防止图片报跨域的错
    // 先利用clip()方法裁剪出个方块儿，让大家认识裁剪
    var x = 150,
      y = 40,
      w = 42,
      r = 10,
      PI = Math.PI; //x坐标、y坐标、正方形的宽、圆的半径、圆周率(3.14...)
    function draw(ctx, operation) {
      ctx.beginPath(); //拿笔
      ctx.moveTo(x, y); //把笔尖点到这个点
      ctx.lineTo(x + w / 2, y); //笔尖画到  正方形上边线中间
      ctx.arc(x + w / 2, y - r + 2, r, 0, 2 * PI); //在坐标点（x+w/2,y-r+2）画一个r为半径的圆，角度开始为0，结束角度为2π，顺时针画个圆
      ctx.lineTo(x + w / 2, y); //笔尖移动到 正方形上边线中间
      ctx.lineTo(x + w, y); //笔尖画到 正方形的上边线的右侧
      ctx.lineTo(x + w, y + w / 2); //笔尖再画到正方形的右边线中间点
      ctx.arc(x + w + r - 2, y + w / 2, r, 0, 2 * PI); //在合适的位置画个圆
      ctx.lineTo(x + w, y + w / 2); //笔尖画到正方形的 右边线中间点
      ctx.lineTo(x + w, y + w); //笔尖画到正方形右边线的底部
      ctx.lineTo(x, y + w); //再画到正方形的下边线的左侧

      if (operation == "clip") {
        ctx.lineTo(x, y + w / 2 + r);
        ctx.arc(x + 2, y + w / 2, r, 0.5 * PI, 1.5 * PI, true); //在合适的位置画个圆 true:逆时针
        ctx.lineTo(x, y + w / 2 - r);
      }
      ctx.lineTo(x, y); //再画到正方形的起始点 形成闭环

      if (operation == "clip") {
        ctx.strokeStyle = "black";
        ctx.lineheight = "1";
        ctx.stroke();
      }
      ctx.fillStyle = "#fff"; //填充背景
      ctx[operation]();

      ctx.beginPath(); //重新开始画
      ctx.arc(x, y + w / 2, r, 1.5 * PI, 0.5 * PI); // 只需要画正方形内的半圆就行，方便背景图片的裁剪
      ctx.globalCompositeOperation = "xor"; //将原图遮盖出一个缺口
      ctx.fill(); //填充颜色 前面没加fillStyle就是白色
    }
    draw(canvas_ctx, "fill");
    draw(block_ctx, "clip");
    // 绘图结束

    // 添加事件
    var self = this;
    self.$nextTick(() => {
      //一、定义了一个获取元素的方法
      function getEle(selector) {
        return document.querySelector(selector);
      }
      //二、获取到需要用到的DOM元素
      var box = getEle("#slide_unloack_wraper"), //容器
        slider = getEle("#slide_unloack_inner"), //滑块
        maxMoveX = box.offsetWidth - 64, //解锁可以滑动的距离 64是写死的
        downX, //用于存放鼠标按下时的位置
        successUnlockX = [130, 170]; //成功解锁活动距离
      //三、给滑块添加鼠标按下事件
      slider.onmousedown = mousedownHandler;
      slider.ontouchstart = mousedownHandler; //移动端加touchstart事件
      //3.1鼠标按下事件的方法实现
      function mousedownHandler(e) {
        slider.style.transition = "";
        var e = e || window.event || e.which;
        downX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
        if (!self.isSuccess) {
          //在鼠标按下时，分别给鼠标添加移动和松开事件
          document.onmousemove = mousemoveHandler;
          document.onmouseup = mouseupHandler;
          //添加移动端对应事件
          document.ontouchmove = mousemoveHandler;
          document.ontouchend = mouseupHandler;
        }
      }
      //四、定义一个获取鼠标当前需要移动多少距离的方法
      function getOffsetX(offset, min, max) {
        if (offset < min) {
          offset = min;
        } else if (offset > max) {
          offset = max;
        }
        return offset;
      }
      //3.1.1鼠标移动事件的方法实现
      function mousemoveHandler(e) {
        var e = e || window.event || e.which;
        var moveX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
        var offsetX = getOffsetX(moveX - downX, 0, maxMoveX);
        slider.style.left = offsetX + "px";
        // e.preventDefault();
      }
      //3.1.2鼠标松开事件的方法实现
      function mouseupHandler(e) {
        var moveX = e.clientX ? e.clientX : e.changedTouches[0].clientX;
        var endX = getOffsetX(moveX - downX, 0, maxMoveX);
        if (endX <= successUnlockX[1] && endX >= successUnlockX[0]) {
          slider.style.left = endX + "px";
          success();
        }
        if (!self.isSuccess) {
          slider.style.left = 0 + "px";
          slider.style.transition = "left 0.5s linear";
        }
        document.onmousemove = null;
        document.onmouseup = null;
        //移除移动端事件
        document.ontouchmove = null;
        document.ontouchend = null;
      }
      //五、定义一个滑块解锁成功的方法
      function success() {
        self.isSuccess = true;
        //滑动成功时，移除鼠标按下事件和鼠标移动事件
        slider.onmousedown = null;
        document.onmousemove = null;
        //移除移动端事件
        document.ontouchstart = null;
        document.ontouchmove = null;
        self.$emit("successUnlock");
      }
    });
  },
  methods: {},
};
</script>

<style scoped>
#slide_unloack_wraper {
  position: relative;
}
#slide_unloack_inner {
  position: absolute;
  left: 0;
  top: 0;
  touch-action: none;
}
</style>
